#pragma once
#include <iostream>
#include <string>
#include <memory>
#include <jsoncpp/json/json.h>

const std::string jsongap = "\r\n";
bool Encode(std::string &message)
{
    if (message.empty())
    {
        std::cerr << "Message is empty" << std::endl;
        return false;
    }
    std::string package = std::to_string(message.size()) + jsongap + message + jsongap;
    message = package;
    return true;
}
bool Decode(std::string &package, std::string *content)
{
    auto pos = package.find(jsongap);
    if (pos == std::string::npos)
    {
        std::cerr << "Invalid package" << std::endl;
        return false;
    }
    std::string conrent_lenth = package.substr(0, pos);
    int length = std::stoi(conrent_lenth);

    // 16\r\n{json}\r\n
    int full_lenth = conrent_lenth.size() + length + jsongap.size() * 2;
    if (full_lenth != package.size())
    {
        std::cerr << "Invalid package length" << std::endl;
        return false;
    }
    *content = package.substr(pos + jsongap.size(), length);
    package.erase(0, full_lenth);
    return true;
}

class Request
{

public:
    Request()
        : _a(0), _b(0), _op('+')
    {
    }
    Request(int a, int b, char op)
        : _a(a), _b(b), _op(op)
    {
    }

    bool Serialize(std::string &out)
    {
        Json::Value root;
        root["a"] = _a;
        root["b"] = _b;
        root["op"] = _op;
        Json::StreamWriterBuilder writer;
        std::unique_ptr<Json::StreamWriter> jsonWriter(writer.newStreamWriter());
        std::stringstream ss;
        jsonWriter->write(root, &ss);
        out = ss.str();
        return true;
    }
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool parsesuccess = reader.parse(in, root);
        if (!parsesuccess)
        {
            std::cerr << "Failed to parse JSON: " << reader.getFormattedErrorMessages();
            return false;
        }
        _a = root["a"].asInt();
        _b = root["b"].asInt();
        _op = root["op"].asInt();
        return true;
    }
    void Print()
    {
        std::cout << _a << std::endl;
        std::cout << _b << std::endl;
        std::cout << _op << std::endl;
    }
    int X() const { return _a; }
    int Y() const { return _b; }
    char Oper() const { return _op; }

private:
    int _a;
    int _b;
    char _op;
};

class Response
{

public:
    Response(int result = 0, int code = 0)
        : _result(result), _code(code)
    {
    }
    bool Serialize(std::string &out)
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::StreamWriterBuilder writer;
        std::unique_ptr<Json::StreamWriter> jsonWriter(writer.newStreamWriter());
        std::stringstream ss;
        jsonWriter->write(root, &ss);
        out = ss.str();
        return true;
    }
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool parsesuccess = reader.parse(in, root);
        if (!parsesuccess)
        {
            std::cerr << "Failed to parse JSON: " << reader.getFormattedErrorMessages();
            return false;
        }
        _result = root["result"].asInt();
        _code = root["code"].asInt();
        return true;
    }
    void Print()
    {
        std::cout << _result << std::endl;
        std::cout << _code << std::endl;
    }
    int Result() const { return _result; }
    int Code() const { return _code; }

private:
    int _result;
    int _code;
};